using System;

namespace needle.Services.astra.Collections
{
	/// <summary>
	/// Base interface for list of items, which can be limitted to its subset.
	/// </summary>
	/// <remarks>
	/// When items are added/removed to/from list, subset is made bigger/smaller to accomodate the changes (made from outside or even propagated from inner list) so that whole added/removed item is/isn`t part of the subset.
	/// </remarks>
	/// <typeparam name="T">Main item type (list can also have other types of items).</typeparam>
	public interface ISubsetListBase<T>
	{
		/// <summary>
		/// Starting index of list subset.
		/// </summary>
		/// <value>Default: 0.</value>
		/// <exception cref="ArgumentOutOfRange">
		/// set: Value is
		///		&lt; 0 or
		///		(&gt;= <see cref="TCount"/> and <see cref="TCount"/> &gt; 0) or
		///		(!= 0 and <see cref="TCount"/> = 0) or
		///		(&gt; <see cref="TEndIndex"/> + 1).</exception>
		int TStartIndex
		{
			get;
			set;
		}
		/// <summary>
		/// Ending index of list subset.
		/// </summary>
		/// <value>
		/// Default: <see cref="TCount"/> - 1 (set with <see cref="int.MaxValue"/>).
		/// set:
		/// If this value is <see cref="int.MaxValue"/>, it means "to the end of the list" (get returns <see cref="TCount"/> - 1).
		/// If this value is <see cref="TStartIndex"/> - 1, sublist has 0 items.
		/// </value>
		/// <exception cref="ArgumentOutOfRange">
		/// set: Value is not in range &lt;<see cref="TStartIndex"/> - 1, <see cref="TCount"/>) and is not <see cref="int.MaxValue"/>.
		/// </exception>
		int TEndIndex
		{
			get;
			set;
		}
		/// <summary>
		/// Starting index of list subset in flat (not dealing with subitems) list.
		/// </summary>
		/// <remarks>If this list is not hierarchical, it is the same as <see cref="TStartIndex"/>.</remarks>
		int FlatStartIndex
		{
			get;
		}
		/// <summary>
		/// Ending index of list subset in flat (not dealing with subitems) list.
		/// </summary>
		/// <remarks>If this list is not hierarchical, it is the same as <see cref="TEndIndex"/>.</remarks>
		int FlatEndIndex
		{
			get;
		}
		/// <summary>
		/// List subset items count from <see cref="TStartIndex"/>.
		/// </summary>
		/// <value>
		/// Default: <see cref="TCount"/> (set with <see cref="int.MaxValue"/>).
		/// set: If this value is <see cref="int.MaxValue"/>, <see cref="TEndIndex"/> is set to this value.
		/// </value>
		/// <exception cref="ArgumentOutOfRange">
		/// set: Value is not in range &lt;0, <see cref="TCount"/> - <see cref="TStartIndex"/>).</exception>
		int SubsetCount
		{
			get;
			set;
		}
		/// <summary>
		/// Number of items of type <typeparamref name="T"/> in full list.
		/// If the list is hierarchical, it contains also items of <see cref="ISubsetListBase{T}"/> type, this count can be different then <see cref="ICollection{}.Count"/> of the list, because number of subitems of <typeparamref name="T"/> type from such sublists is added to the whole count (and sublists are not counted).
		/// </summary>
		int TCount
		{
			get;
		}

		/// <summary>
		/// Sets <see cref="TStartIndex"/>, <see cref="TEndIndex"/> and <see cref="SubCount"/> to their defaults.
		/// This makes accessible whole list.
		/// </summary>
		void ResetSubset();
		/// <summary>
		/// Sets subset range.
		/// </summary>
		/// <param name="startIndex">See <see cref="TStartIndex"/>.</param>
		/// <param name="endIndex">See <see cref="TEndIndex"/>.</param>
		void SetSubsetIndex(int startIndex, int endIndex);
		/// <summary>
		/// Sets subset range.
		/// </summary>
		/// <param name="startIndex">See <see cref="TStartIndex"/>.</param>
		/// <param name="subsetCount">See <see cref="SubsetCount"/>.</param>
		void SetSubsetCount(int startIndex, int subsetCount);
	}
}
